// DrawPolygon
/*
绘制面
 */
class DrawPolygon {
  constructor(arg) {
    this.Cesium = arg.Cesium;
    this.callback = arg.callback;
    this._polygon = null; //活动面
    this._polygonLast = null; //最后一个面
    this._positions = []; //活动点
    this._entities_point = []; //脏数据
    this._entities_polygon = []; //脏数据
    this._polygonData = null; //用户构造面
    this._entities_labels = []; //用于显示面积结果
    this.currentHeight = 0.0;
    this.maxValue = 0.0;
  }

  setViewer(earth) {
    this.viewer = earth.czm.viewer;
  }

  setThisWidget() {
    let self = this;
    this.thisWidget = {
      entity: null,
      drawOk: function(e) {
        this.entity = e;
        var t = this.computePolygonHeightRange(
          e.polygon.hierarchy.getValue().positions
        );
        (this.currentHeight = t.minHeight), (this.maxValue = t.maxHeight);
      },
      computePolygonHeightRange: function(e) {
        let viewer = self.viewer;
        var t = [];
        for (var i = 0; i < e.length; i++) t.push(e[i].clone());
        var a,
          n,
          r,
          o,
          s,
          u,
          l,
          h = 0,
          g = 9999,
          c = Math.PI / Math.pow(2, 11) / 64,
          m = new Cesium.PolygonGeometry.fromPositions({
            positions: t,
            vertexFormat: Cesium.PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
            granularity: c,
          }),
          d = new Cesium.PolygonGeometry.createGeometry(m);
        for (i = 0; i < d.indices.length; i += 3)
          (a = d.indices[i]),
            (n = d.indices[i + 1]),
            (r = d.indices[i + 2]),
            (l = new Cesium.Cartesian3(
              d.attributes.position.values[3 * a],
              d.attributes.position.values[3 * a + 1],
              d.attributes.position.values[3 * a + 2]
            )),
            (o = viewer.scene.globe.getHeight(
              Cesium.Cartographic.fromCartesian(l)
            )) < g && (g = o),
            h < o && (h = o),
            (l = new Cesium.Cartesian3(
              d.attributes.position.values[3 * n],
              d.attributes.position.values[3 * n + 1],
              d.attributes.position.values[3 * n + 2]
            )),
            (s = viewer.scene.globe.getHeight(
              Cesium.Cartographic.fromCartesian(l)
            )) < g && (g = s),
            h < s && (h = s),
            (l = new Cesium.Cartesian3(
              d.attributes.position.values[3 * r],
              d.attributes.position.values[3 * r + 1],
              d.attributes.position.values[3 * r + 2]
            )),
            (u = viewer.scene.globe.getHeight(
              Cesium.Cartographic.fromCartesian(l)
            )) < g && (g = u),
            h < u && (h = u);
        return {
          maxHeight: h,
          minHeight: g,
        };
      },
      startFx: function(e) {
        self.viewer.scene.globe.depthTestAgainstTerrain = !0;
        var t = self;
        (this.extrudedHeight = e),
          (this.entity.polygon.extrudedHeight = new Cesium.CallbackProperty(
            function(e) {
              return t.extrudedHeight;
            },
            false
          ));

        for (
          var i = this.entity.polygon.hierarchy.getValue().positions, a = [], n = 0;
          n < i.length;
          n++
        ) {
          var r = Cesium.Ellipsoid.WGS84.cartesianToCartographic(i[n]),
            o = {
              lon: Cesium.Math.toDegrees(r.longitude),
              lat: Cesium.Math.toDegrees(r.latitude),
              hgt: e,
            },
            s = [o.lon, o.lat, o.hgt];
          a = a.concat(s);
        }
        return (
          (i = Cesium.Cartesian3.fromDegreesArrayHeights(a)),
          (this.entity.polygon.hierarchy = new Cesium.CallbackProperty(function(
            e
          ) {
            return i;
          },
          false)),
          !0
        );
      },
      clear: function() {
        (this.viewer.scene.globe.depthTestAgainstTerrain = !1),
          (this.entity = null);
      },
      updateHeight: function(e) {
        this.entity.polygon.extrudedHeight = e;
      },
    };
  }

  //返回最后活动面
  get polygon() {
    return this._polygonLast;
  }

  //返回面数据用于加载面
  getData() {
    return this._polygonData;
  }

  //加载面
  loadPolygon(data) {
    var $this = this;
    let uid = $this.guid();
    this.viewer.entities.add({
      id: uid,
      polygon: {
        hierarchy: new $this.Cesium.PolygonHierarchy(data),
        // perPositionHeight: true,
        show: true,
        fill: true,
        material: new Cesium.ColorMaterialProperty(Cesium.Color.LIGHTSKYBLUE.withAlpha(0.7)),
        // width: 3,
        // outlineColor: $this.Cesium.Color.BLACK,
        // outlineWidth: 1,
        // outline: true,
        clampToGround: true,
      },
    });
    return uid;
  }

  //开始绘制
  startCreate() {
    var $this = this;
    $this.clear();
    this.viewer.entities.add({
	name: 'Green cylinder with black outline',
	position: Cesium.Cartesian3.fromDegrees(-100.0, 40.0, 200000.0),
	cylinder: {
		length: 400000.0,
		topRadius: 200000.0,
		bottomRadius: 200000.0,
		material: Cesium.Color.GREEN.withAlpha(0.5),
		outline: true,
		outlineColor: Cesium.Color.DARK_GREEN
	},
	show:false
	});
    this.handler = new this.Cesium.ScreenSpaceEventHandler(
      this.viewer.scene.canvas
    );
    this.handler.setInputAction(function(evt) {
      // console.log('left click')
      const pick = $this.viewer.scene.pick(evt.position);
      if (pick && pick.id) {
        if (pick.id.label && pick.id.label.text._value === "结束画面") {
          if (!$this._polygon) return;
          // $this._positions.pop()
          $this._polygonData = $this._positions.concat();
          $this.viewer.entities.remove($this._positions); //移除
          var polygon_id = $this.loadPolygon($this._polygonData);
          $this._entities_polygon.push(polygon_id);
          $this._polygonLast = polygon_id;
          $this.viewer.entities.getById(
            $this._entities_point[$this._entities_point.length - 1]
          ).label = null; //去除结束画面标签

          //   var labelpostion = $this.getCentroid($this._polygonLast.polygon) //得到多边形质心
          //   var area = $this.getSurfaceArea($this._polygonData).toFixed(3)
          //   $this._entities_labels.push(
          //     $this.viewer.entities.add({
          //       position: labelpostion,
          //       label: {
          //         //文字标签
          //         text: '面积：' + area.toString(),
          //         font: '500 30px Helvetica', // 15pt monospace
          //         scale: 0.5,
          //         style: Cesium.LabelStyle.FILL,
          //         fillColor: Cesium.Color.WHITE,
          //         pixelOffset: new Cesium.Cartesian2(0, -40), //偏移量
          //         showBackground: true,
          //         backgroundColor: new Cesium.Color(26 / 255, 196 / 255, 228 / 255, 1.0)
          //       }
          //     })
          //   )
          //#endregion
          // if (typeof $this.callback == 'function') {
          //   $this.callback(Polygon)
          // }
          let param = [];
          var ellipsoid = $this.viewer.scene.globe.ellipsoid;
          for (var i = 0; i < $this._positions.length; i++) {
            var cartographic = ellipsoid.cartesianToCartographic(
              $this._positions[i]
            );
            var lat = $this.Cesium.Math.toDegrees(cartographic.latitude);
            var lng = $this.Cesium.Math.toDegrees(cartographic.longitude);
            var height = cartographic.height;
            param.push(lng);
            param.push(lat);
            param.push(height);
          }
          //   $this.clear()
          $this.destroy();
          $this.thisWidget.drawOk($this.viewer.entities.getById(polygon_id));
        //   $this.thisWidget.startFx(4.0);
          $this.int = self.setInterval(() => {
            $this.thisWidget.currentHeight > $this.thisWidget.maxValue
              ? (clearInterval($this.int))
              : ($this.thisWidget.updateHeight($this.thisWidget.currentHeight),
                ($this.thisWidget.currentHeight += 1));
          }, 100);
          return;
        }
      }
      //单击开始绘制
      var cartesian = $this.getCatesian3FromPX(evt.position);
      // if ($this._positions.length == 0) {
      //   $this._positions.push(cartesian.clone())
      // }
      let uid = $this.guid();
      $this.createPoint(cartesian, uid);
      $this._positions.push(cartesian);
    }, $this.Cesium.ScreenSpaceEventType.LEFT_CLICK);

    this.handler.setInputAction(function(evt) {
      //移动时绘制面
      if ($this._positions.length < 1) return;
      var cartesian = $this.getCatesian3FromPX(evt.endPosition);
      if ($this._positions.length == 3) {
        if (!$this.Cesium.defined($this._polygon)) {
          let uid = $this.guid();
          $this._polygon = $this.createPolygon(uid);
        }
      }
      $this._positions.push(cartesian);
      $this._positions.pop();
    }, $this.Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  }

  //创建面
  createPolygon(uid) {
    var $this = this;
    this.viewer.entities.add({
      id: uid,
      polygon: {
        hierarchy: new $this.Cesium.CallbackProperty(function() {
          return new $this.Cesium.PolygonHierarchy($this._positions);
        }, false),
        // perPositionHeight: true,
        show: true,
        fill: true,
        material: $this.Cesium.Color.RED.withAlpha(0.8),
        width: 5,
        outlineColor: $this.Cesium.Color.BLACK,
        outlineWidth: 1,
        outline: true,
        clampToGround: true,
      },
    });
    $this._entities_polygon.push(uid);
    return uid;
  }

  //创建点
  createPoint(cartesian, uid) {
    if (this._entities_point.length > 1 && this._positions.length > 1) {
      var last_point = this.viewer.entities.getById(
        this._entities_point[this._entities_point.length - 1]
      );
      last_point.label = null;
      last_point.billboard = null;
    }

    var $this = this;
    var point;
    if (this._positions.length >= 2) {
      point = this.viewer.entities.add({
        id: uid,
        position: cartesian,
        point: {
          pixelSize: 10,
          color: $this.Cesium.Color.YELLOW,
        },
        label: {
          //文字标签
          text: "结束画面",
          font: "500 15px Helvetica", // 15pt monospace
          scale: 1.0,
          style: Cesium.LabelStyle.FILL,
          fillColor: Cesium.Color.WHITE,
          pixelOffset: new Cesium.Cartesian2(0, -70), //偏移量
          showBackground: true,
          backgroundColor: new Cesium.Color(
            26 / 255,
            196 / 255,
            228 / 255,
            1.0
          ),
        },
      });
    } else {
      point = this.viewer.entities.add({
        id: uid,
        position: cartesian,
        point: {
          pixelSize: 10,
          color: $this.Cesium.Color.YELLOW,
        },
      });
    }
    $this._entities_point.push(uid);
    return point;
  }

  //销毁事件
  destroy() {
    if (this.handler) {
      this.handler.destroy();
      this.handler = null;
    }
  }

  //清空实体对象
  clear() {
    for (var i = 0; i < this._entities_point.length; i++) {
      this.viewer.entities.removeById(this._entities_point[i]);
    }
    for (var j = 0; j < this._entities_polygon.length; j++) {
      this.viewer.entities.removeById(this._entities_polygon[j]);
    }

    for (var m = 0; m < this._entities_polygon.length; m++) {
      this.viewer.entities.removeById(this._entities_labels[m]);
    }

    this._polygon = null; //活动面
    this._polygonLast = null; //最后一个面
    this._positions = []; //活动点
    this._entities_point = []; //脏数据
    this._entities_polygon = []; //脏数据
    this._polygonData = null; //用户构造面
  }

  getCatesian3FromPX(px) {
    // 两个pick联合使用，可以解决pickPosition不稳定的问题和global.pick不能找模型高度的问题
    var cartesian1;
    var cartesian2;
    var ray = this.viewer.camera.getPickRay(px);
    if (!ray) return null;
    cartesian1 = this.viewer.scene.globe.pick(ray, this.viewer.scene);

    if (this.viewer.scene.pickPositionSupported) {
      if (this.viewer.scene.mode !== Cesium.SceneMode.MORPHING) {
        this.viewer.scene.globe.depthTestAgainstTerrain = true;
        cartesian2 = this.viewer.scene.pickPosition(px);
      }
    } else {
      //如果不支持pickPosition,则返回undefined
      console.log("This browser does not support pickPosition.");
      cartesian2 = undefined;
    }

    let real_cartesian = cartesian2;
    if (
      typeof cartesian2 == "undefined" ||
      cartesian2.height > 8848 ||
      cartesian2.height < 0
    ) {
      real_cartesian = cartesian1;
    }
//     return real_cartesian;
    return cartesian1
  }

  //用海伦公式获取传入坐标的构成的多边形的面积。
  getSurfaceArea(positions) {
    if (positions.length < 3) {
      return 0;
    }
    const {
      Cartesian3,
      EllipsoidTangentPlane,
      Ellipsoid,
      Math: CesiumMath,
      PolygonGeometryLibrary,
      PolygonHierarchy,
      VertexFormat,
    } = Cesium;
    const perPositionHeight = true;
    // 获取组成多边形的三角形。
    const tangentPlane = EllipsoidTangentPlane.fromPoints(
      positions,
      Ellipsoid.WGS84
    );
    const polygons = PolygonGeometryLibrary.polygonsFromHierarchy(
      new PolygonHierarchy(positions),
      tangentPlane.projectPointsOntoPlane.bind(tangentPlane),
      !perPositionHeight,
      Ellipsoid.WGS84
    );

    const geom = PolygonGeometryLibrary.createGeometryFromPositions(
      Ellipsoid.WGS84,
      polygons.polygons[0],
      CesiumMath.RADIANS_PER_DEGREE,
      perPositionHeight,
      VertexFormat.POSITION_ONLY
    );

    if (
      geom.indices.length % 3 !== 0 ||
      geom.attributes.position.values.length % 3 !== 0
    ) {
      // 不是三角形，无法计算。
      return 0;
    }
    const coords = [];
    for (let i = 0; i < geom.attributes.position.values.length; i += 3) {
      coords.push(
        new Cartesian3(
          geom.attributes.position.values[i],
          geom.attributes.position.values[i + 1],
          geom.attributes.position.values[i + 2]
        )
      );
    }
    let area = 0;
    for (let i = 0; i < geom.indices.length; i += 3) {
      const ind1 = geom.indices[i];
      const ind2 = geom.indices[i + 1];
      const ind3 = geom.indices[i + 2];

      const a = Cartesian3.distance(coords[ind1], coords[ind2]);
      const b = Cartesian3.distance(coords[ind2], coords[ind3]);
      const c = Cartesian3.distance(coords[ind3], coords[ind1]);

      // 海伦公式
      const s = (a + b + c) / 2.0;
      area += Math.sqrt(s * (s - a) * (s - b) * (s - c));
    }
    return area;
  }

  /**
   * generateUUID 生成UUID
   * @returns {string} 返回字符串
   */
  generateUUID() {
    var d = new Date().getTime();
    var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(
      c
    ) {
      var r = (d + Math.random() * 16) % 16 | 0;
      d = Math.floor(d / 16);
      return (c == "x" ? r : (r & 0x7) | 0x8).toString(16);
    });
    return uuid;
  }

  // 获取多边形的质心
  getCentroid(pgon) {
    var value = [];
    var center = [];
    var a = 0;
    var b = 0;
    for (var j = 0; j <= pgon._hierarchy._value.positions.length - 1; j++) {
      value[j] = [
        pgon._hierarchy._value.positions[j].x,
        pgon._hierarchy._value.positions[j].y,
      ];
      a = pgon._hierarchy._value.positions[j].z;
      b = b + a;
    }

    // 让最后一个点与第一个点相同才能让turf组成多边形
    value[pgon._hierarchy._value.positions.length] = [
      pgon._hierarchy._value.positions[0].x,
      pgon._hierarchy._value.positions[0].y,
    ];

    // eslint-disable-next-line no-undef
    var polygon = turf.polygon([value]);
    // eslint-disable-next-line no-undef
    var centroid = turf.centroid(polygon);
    center = [
      centroid.geometry.coordinates[0],
      centroid.geometry.coordinates[1],
      b / pgon._hierarchy._value.positions.length,
    ];
    return Cesium.Cartesian3.fromArray(center);
  }

  guid() {
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
      var r = (Math.random() * 16) | 0,
        v = c == "x" ? r : (r & 0x3) | 0x8;
      return v.toString(16);
    });
  }
}

export default DrawPolygon;
